﻿<!DOCTYPE html>
<html>
<head>
  <meta charset="UTF-8">
  <title>Simulating Input Events</title>
  <meta name="description" content="Test a diagram by simulating abstract input events." />
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <!-- Copyright 1998-2019 by Northwoods Software Corporation. -->

  <script src="../release/go.js"></script>
  <script src="../assets/js/goSamples.js"></script>  <!-- this is only for the GoJS Samples framework -->
  <script src="Robot.js"></script>

  <script id="code">
    var robot;  // this global variable will hold an instance of the Robot class for myDiagram

    function init() {
      if (window.goSamples) goSamples();  // init for these samples -- you don't need to call this
      var $ = go.GraphObject.make;  // for conciseness in defining templates

      function showProperties(e, obj) {  // executed by ContextMenuButton
        var node = obj.part.adornedPart;
        var msg = "Context clicked: " + node.data.key + ". ";
        msg += "Selection includes:";
        myDiagram.selection.each(function(part) {
          msg += " " + part.toString();
        });
        document.getElementById("myStatus").textContent = msg;
      }

      function nodeClicked(e, obj) {  // executed by click and doubleclick handlers
        var evt = e.copy();
        var node = obj.part;
        var type = evt.clickCount === 2 ? "Double-Clicked: " : "Clicked: ";
        var msg = type + node.data.key + ". ";
        document.getElementById("myStatus").textContent = msg;
      }

      myDiagram =
        $(go.Diagram, "myDiagramDiv",  // must name or refer to the DIV HTML element
          {
            nodeTemplate:
              $(go.Node, "Auto",
                {
                  click: nodeClicked,
                  doubleClick: nodeClicked,
                  contextMenu:
                    $("ContextMenu",
                      $("ContextMenuButton",
                        $(go.TextBlock, "Properties"),
                        { click: showProperties })
                    )
                },
                $(go.Shape, "Rectangle",
                  { fill: "lightgray" },
                  { portId: "", fromLinkable: true, toLinkable: true, cursor: "pointer" }),
                $(go.TextBlock,
                  { margin: 3 },
                  new go.Binding("text", "key"))),
            model: new go.GraphLinksModel([
              { key: "Lambda" },
              { key: "Mu" }
            ], [
                { from: "Lambda", to: "Mu" }
              ]),
            "undoManager.isEnabled": true
          });

      // a shared Robot that can be used by all commands for this one Diagram
      robot = new Robot(myDiagram);  // defined in Robot.js

      // initialize the Palette that is on the left side of the page
      myPalette =
        $(go.Palette, "myPaletteDiv",  // must name or refer to the DIV HTML element
          {
            nodeTemplate: myDiagram.nodeTemplate,
            model: new go.GraphLinksModel([  // specify the contents of the Palette
              { key: "Alpha" },
              { key: "Beta" },
              { key: "Gamma" },
              { key: "Delta" }
            ])
          });
    }

    function dragFromPalette() {
      // simulate a drag-and-drop between Diagrams:
      var dragdrop = { sourceDiagram: myPalette, targetDiagram: myDiagram };
      robot.mouseDown(5, 5, 0, dragdrop);  // this should be where the Alpha node is in the source myPalette
      robot.mouseMove(60, 60, 100, dragdrop);
      robot.mouseUp(100, 100, 200, dragdrop);  // this is where the node will be dropped in the target myDiagram
      // If successful in dragging a node from the Palette into the Diagram,
      // the DraggingTool will perform a transaction.
    }

    function copyNode() {
      var alpha = myDiagram.findNodeForKey("Alpha");
      if (alpha === null) return;
      var loc = alpha.actualBounds.center;

      var options = { control: true, alt: true };
      // Simulate a mouse drag to move the Alpha node:
      robot.mouseDown(loc.x, loc.y, 0, options);
      robot.mouseMove(loc.x + 80, loc.y + 50, 50, options);
      robot.mouseMove(loc.x + 20, loc.y + 100, 100, options);
      robot.mouseUp(loc.x + 20, loc.y + 100, 150, options);
      // If successful, will have made a copy of the "Alpha" node below it.

      // Alternatively you could copy the Node using commands:
      // myDiagram.commandHandler.copySelection();
      // myDiagram.commandHandler.pasteSelection(new go.Point(loc.x+20, loc.y+100));
    }

    function dragSelectNodes() {
      var alpha = myDiagram.findNodeForKey("Alpha");
      if (alpha === null) return;
      var alpha2 = myDiagram.findNodeForKey("Alpha2");
      if (alpha2 === null) return;
      var coll = new go.Set();
      coll.add(alpha);
      coll.add(alpha2);
      var area = myDiagram.computePartsBounds(coll);
      area.inflate(30, 30);

      // Simulate dragging in the background around the two Alpha nodes.
      // This uses timestamps to pretend to wait a while to avoid activating the PanningTool.
      // Hopefully this mouse down does not hit any Part, but in the Diagram's background:
      robot.mouseDown(area.x, area.y, 0);
      // NOTE that this mouseMove timestamp needs to be > myDiagram.toolManager.dragSelectingTool.delay:
      robot.mouseMove(area.centerX, area.centerY, 200);
      robot.mouseUp(area.right, area.bottom, 250);
      // Now should have selected both "Alpha" and "Alpha2" using the DragSelectingTool.

      // Alternatively you could select the Nodes programmatically:
      // alpha.isSelected = true;
      // alpha2.isSelected = true;
    }

    function clickContextMenu() {
      var alpha = myDiagram.findNodeForKey("Alpha");
      if (alpha === null) return;
      var loc = alpha.location;

      // right click on Alpha
      robot.mouseDown(loc.x + 10, loc.y + 10, 0, { right: true });
      robot.mouseUp(loc.x + 10, loc.y + 10, 100, { right: true });

      // Alternatively you could invoke the Show Context Menu command directly:
      // myDiagram.commandHandler.showContextMenu(alpha);

      // move mouse over first context menu button
      robot.mouseMove(loc.x + 20, loc.y + 20, 200);
      // and click that button
      robot.mouseDown(loc.x + 20, loc.y + 20, 300);
      robot.mouseUp(loc.x + 20, loc.y + 20, 350);
      // This should have invoked the ContextMenuButton's click function, showProperties,
      // which should have put a green message in the myStatus DIV.
    }

    function deleteSelection() {
      // Simulate clicking the "Del" key:
      robot.keyDown("Del");
      robot.keyUp("Del");
      // Now the selected Nodes are deleted.

      // Alternatively you could invoke the Delete command directly:
      // myDiagram.commandHandler.deleteSelection();
    }

    function clickLambda() {
      var lambda = myDiagram.findNodeForKey("Lambda");
      if (lambda === null) return;
      var loc = lambda.location;

      // click on Lambda
      robot.mouseDown(loc.x + 10, loc.y + 10, 0, {});
      robot.mouseUp(loc.x + 10, loc.y + 10, 100, {});

      // Clicking is just a sequence of input events.
      // There is no command in CommandHandler for such a basic gesture.
    }

    function doubleClickLambda() {
      var lambda = myDiagram.findNodeForKey("Lambda");
      if (lambda === null) return;
      var loc = lambda.location;

      // double-click on Lambda
      robot.mouseDown(loc.x + 10, loc.y + 10, 0, {});
      robot.mouseUp(loc.x + 10, loc.y + 10, 100, {});
      robot.mouseDown(loc.x + 10, loc.y + 10, 200, { clickCount: 2 });
      robot.mouseUp(loc.x + 10, loc.y + 10, 300, { clickCount: 2 });
    }

  </script>
</head>
<body onload="init()">
<div id="sample">
  <div style="width: 100%; display: flex; justify-content: space-between">
    <div id="myPaletteDiv" style="width: 80px; height: 400px; margin-right: 2px; border: solid 1px black"></div>
    <div id="myDiagramDiv" style="flex-grow: 1; height: 400px; border: solid 1px black"></div>
  </div>
  <p>
  To simulate mouse events the buttons below use the <b>Robot</b> class that is defined in <a href="Robot.js">Robot.js</a>.
  </p>
  <p>
  Click these buttons in order from top to bottom:<br />
  <button onclick="dragFromPalette()">Drag From Palette</button><br />
  <button onclick="copyNode()">Copy Node</button><br />
  <button onclick="dragSelectNodes()">Drag Select Nodes</button><br />
  <button onclick="clickContextMenu()">Context Menu Click Alpha</button><br />
  <button onclick="deleteSelection()">Delete</button><br />
  </p>
  <p>Clicking operations:<br />
  <button onclick="clickLambda()">Click Lambda</button><br />
  <button onclick="doubleClickLambda()">Double Click Lambda</button><br />
  </p>
  <p>
  The <a>UndoManager</a> has been enabled in the main Diagram.
  Give focus to the Diagram and you can undo everything and then redo everything to confirm what was executed by the Robot.
  </p>
  <div id="myStatus" style="color:green"></div>
</div>
</body>
</html>
